#
# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
#
import sys
import re
import types
from types import *
import vnc_api_service

# dictionary representation to XML representation


def dict_to_elem(wrap_tag, obj_dict):
    xml_str = "<%s>" % (wrap_tag)
    for fname in obj_dict:
        if isinstance(obj_dict[fname], dict):
            # call recursively with dict
            xml_str += dict_to_elem(fname, obj_dict[fname])
        else:
            xml_str += "<%s>%s</%s>" % (fname, obj_dict[fname], fname)

    xml_str += "</%s>" % (wrap_tag)

    return xml_str

# XML representation to dictionary representation


def elem_to_dict(obj_elem):
    obj_dict = {}

    for field in obj_elem.getchildren():
        fname = re.sub("{.*}", "", field.tag)
        if not field.text and not field.getchildren():
            return {}

        if not field.text:
            val = elem_to_dict(field)
        elif (field.text.isdigit()):
            val = int(field.text)
        else:
            val = unicode(field.text)

        obj_dict[fname] = val

    return obj_dict

# convert object to dictionary representation


def obj_to_dict(obj):
    obj_dict = {}
    for fname in obj.__dict__:
        if obj.__dict__[fname] is None:
            continue
        val = obj.__dict__[fname]
        if isinstance(val, str):
            # unicode it if field is string
            val = unicode(val)
        elif isinstance(obj.__dict__[fname], InstanceType):
            # call recursively if field is object
            val = obj_to_dict(val)

        obj_dict[unicode(fname)] = val

    return obj_dict


def subnet_elem_to_dict(sn_elem):
    # TODO replace with autogenerated code
    sn_d = {}
    for field in sn_elem.getchildren():
        fname = re.sub("{.*}", "", field.tag)
        if (field.text.isdigit()):
            sn_d[fname] = int(field.text)
        else:
            sn_d[fname] = unicode(field.text)

    return sn_d


def subnet_obj_to_dict(sn_obj):
    return obj_to_dict(sn_obj)


def subnet_dict_to_obj(sn_dict):
    # construct object from dict contents

    # will fail if server's obj defn has more fields than client's defn :(
    #kwargs = {}
    # for fname in sn_dict:
    #    kwargs[fname] = sn_dict[fname]
    #sn_obj = vnc_api_service.subnet_s(**kwargs)

    sn_obj = vnc_api_service.subnet_s()
    sn_obj.__dict__.update(sn_dict)

    return sn_obj


def vn_dict_to_obj(vn_dict):
    # construct object from dict contents

    # will fail if server's obj defn has more fields than client's defn :(
    #kwargs = {}
    # for fname in vn_dict:
    #    kwargs[fname] = vn_dict[fname]
    #vn_obj = vnc_api_service.vn_s(**kwargs)

    vn_obj = vnc_api_service.vn_s()
    vn_obj.__dict__.update(vn_dict)

    if vn_obj.vn_subnets:
        # construct list of sn objs
        vn_obj.vn_subnets = []
        for sn_dict in vn_dict['vn_subnets']:
            vn_obj.vn_subnets.append(subnet_dict_to_obj(sn_dict))

    return vn_obj


def policy_dict_to_obj(policy_dict):
    # construct object from dict contents

    # will fail if server's obj defn has more fields than client's defn :(
    #kwargs = {}
    # for fname in vn_dict:
    #    kwargs[fname] = vn_dict[fname]
    #vn_obj = vnc_api_service.vn_s(**kwargs)

    policy_obj = vnc_api_service.policy_s()
    policy_obj.__dict__.update(policy_dict)
    return policy_obj


def sg_rule_elem_to_dict(sg_rule_elem):
    return elem_to_dict(sg_rule_elem)


def sg_rule_dict_to_elem(sg_rule_d):
    return dict_to_elem("sg_rule", sg_rule_d)


def sg_rule_obj_to_dict(sg_rule_obj):
    return obj_to_dict(sg_rule_obj)


def policy_entry_elem_to_dict(policy_entry_elem):
    return elem_to_dict(policy_entry_elem)


def policy_entry_dict_to_elem(policy_entry_d):
    return dict_to_elem("policy_entry", policy_entry_d)


def policy_entry_obj_to_dict(policy_entry_obj):
    return obj_to_dict(policy_entry_obj)
